package com.qd.pay.service;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cdqidi.util.CsvUtil;
import com.cdqidi.util.DateUtil;
import com.cdqidi.util.FileUtil;
import com.qd.pay.config.PayInfoConfig;
import com.qd.pay.model.TfBills;
import com.qd.pay.model.TfBillsTime;
import com.qd.tfpay.order.AccountBO;
import com.qd.tfpay.order.OrderApi;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVRecord;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * @author sjk
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class TfBillService {

    private final OrderApi orderApi;

    private final PayInfoConfig payInfoConfig;
    private final TfBillsTimeService tfBillsTimeService;

    private final TfBillsService tfBillsService;

    private static final String[] TF_BILL_HEADS = {"平台交易流水号", "服务商号(直连商户号)", "特约商户号", "交易金额", "商户订单号", "原商户订单号", "币种", "交易状态", "交易类型"
            , "平台手续费", "特约商户手续费", "清算时间", "交易创建时间", "支付完成时间", "通道方流水号", "用户编号", "用户子编号"};

    @Transactional(rollbackFor = Exception.class)
    public void downloadBill(String date,String partner) throws IOException {
        if (!StringUtils.hasLength(date)) {
            date = DateUtil.localDateToString(LocalDate.now().plusDays(-1), "yyyyMMdd");
        }
        log.info("date: {}", date);
        AccountBO accountBO = orderApi.downloadAccount(partner, date);
        log.info("下载天府银行对账文件:{}", accountBO.getStatus());
        if (accountBO.getStatus().equals(AccountBO.STATUS_SUCCESS)) {
            boolean isUpdate = true;
            //成功的时候才处理
            TfBillsTime data = tfBillsTimeService.getUniqueByPartnerAndOrderDate(partner, date);
            if (null == data) {
                data = new TfBillsTime();
                isUpdate = false;
            }
            data.setOrderCount(accountBO.getOrderCount());
            data.setOrderDate(accountBO.getOrderDate());
            data.setPartner(partner);
            data.setOrderMoney(new BigDecimal(accountBO.getOrderMoney()));
            if (isUpdate) {
                tfBillsTimeService.updateById(data);
            } else {
                tfBillsTimeService.save(data);
            }

            final String base64file = accountBO.getBase64file();
            if (StringUtils.hasLength(base64file)) {
                File f = new File(payInfoConfig.getTfBillPath());
                if (!f.exists()) {
                    log.info("创建文件夹: {}", f.mkdirs());
                }
                final byte[] zipFile = Base64Decoder.decode(base64file);
                FileUtil.createFile(zipFile, payInfoConfig.getTfBillPath(), data.getPartner() + "_" + date + ".zip");
                final File csvFile = ZipUtil.unzip(f.getPath() + File.separator + data.getPartner() + "_" + date + ".zip");
                f = new File(csvFile.getPath());
                if (!f.exists()) {
                    log.error("文件夹不存在,path:{}", f.getPath());
                    return;
                }
                final File[] files = f.listFiles();
                if (null == files) {
                    return;
                }
                log.info("zip文件夹下面存在的文件数量:{}", files.length);
                for (File file : files) {
                    final byte[] csvFileByte = cn.hutool.core.io.FileUtil.readBytes(file);
                    billImportDb(csvFileByte, date, data.getPartner(), data.getSubpartner());
                }
                //保留zip文件，删除解压后的目录和文件
                cn.hutool.core.io.FileUtil.del(f.getPath());
            }
            data.freeData();
        }

        accountBO.freeData();
    }


    public void billImportDb(byte[] file, String billDate, String partner, String subPartner) throws IOException {
        List<CSVRecord> cList = CsvUtil.readCSV(file, TF_BILL_HEADS, "|");
        final TfBillsTime tfBillsTime = tfBillsTimeService.getUniqueByPartnerAndOrderDate(partner, billDate);
        if (null == tfBillsTime) {
            return;
        }
        if (!cList.isEmpty()) {
            final QueryWrapper<TfBills> queryWrapper = new QueryWrapper<TfBills>().eq("partner", partner).eq("clear_time", billDate);
            if (StringUtils.hasLength(subPartner)) {
                queryWrapper.eq("subpartner", subPartner);
            }
            tfBillsService.getBaseMapper().delete(queryWrapper);
            queryWrapper.clear();

            final List<TfBills> tfBills = getTfBills(cList, tfBillsTime.getBid());
            tfBillsService.saveBatch(tfBills);
            tfBills.clear();
        }
    }

    private List<TfBills> getTfBills(List<CSVRecord> cList, String bid) {
        List<TfBills> list = new ArrayList<>();
        if (!cList.isEmpty()) {
            for (CSVRecord r : cList) {
                TfBills data = new TfBills();
                data.setBid(bid);
                data.setTransactionNo(replace(r.get("平台交易流水号")));
                data.setPartner(replace(r.get("服务商号(直连商户号)")));
                data.setSubpartner(replace(r.get("特约商户号")));
                final String totalFeeStr = replace(r.get("交易金额"));
                if (StringUtils.hasLength(totalFeeStr)) {
                    data.setTotalFee(new BigDecimal(totalFeeStr));
                }
                data.setOutTradeNo(replace(r.get("商户订单号")));
                data.setPrimaryOutTradeNo(replace(r.get("原商户订单号")));
                final String feeTypeStr = replace(r.get("币种"));
                if (StringUtils.hasLength(feeTypeStr)) {
                    data.setFeeType(Integer.parseInt(feeTypeStr));
                }
                final String tradeStateStr = replace(r.get("交易状态"));
                if (StringUtils.hasLength(tradeStateStr)) {
                    data.setTradeState(Integer.parseInt(tradeStateStr));
                }
                data.setTradeType(replace(r.get("交易类型")));
                final String platChargeStr = replace(r.get("平台手续费"));
                if (StringUtils.hasLength(platChargeStr)) {
                    data.setPlatcharge(new BigDecimal(platChargeStr));
                }
                final String subPlatChargeStr = replace(r.get("特约商户手续费"));
                if (StringUtils.hasLength(subPlatChargeStr)) {
                    data.setSubplatcharge(new BigDecimal(subPlatChargeStr));
                }
                data.setClearTime(replace(r.get("清算时间")));
                data.setTimeStart(replace(r.get("交易创建时间")));
                data.setTimeEnd(replace(r.get("支付完成时间")));
                data.setChannelNo(replace(r.get("通道方流水号")));
                list.add(data);
            }
        }
        return list;
    }

    private String replace(String str) {
        if (null == str || "".equals(str)) {
            return "";
        }
        return str.replace("`", "");
    }
}
